// linked list Structure added .. going to be used in hash table
/*

makedir /c/u
movedir /a/b/c/r/t
listdir / 1 output1
listdir / 1 output2
*/
//create a linked list of file descriptors(incomplete task)

// insertion sort

#include"main.h"
//extern struct LinkedList *hashtable[26][26];

void initialiseHashTable()
{

    int i,j;
//    fprintf(errfptr,"HashTable.c : method name:initialiseHashTable status:entered\n");
count_of_searchfile=0;


    for (i=0; i<127; i++)
    {


            hashtable[i]=NULL;

    }
  //  fprintf(errfptr,"HashTable.c : method name:initialiseHashTable status:exit1\n");

}

void insert_InSortedOrder(struct LinkedList *temp,int index)//,int index_2)
{

    struct LinkedList *temp_prev=temp;
    struct LinkedList *head=hashtable[index];//[index_2];
    int flag=0;
   // fprintf(errfptr,"HashTable.c : method name:insert_InSortedOrder status:entered\n");
    /*temp=head;
    while(temp!=NULL){
    	printf("  one %s  ",temp->data->filename);
    	temp=temp->next;
    }
    printf("\n\n");
    temp=head->next;*/

    if(strcmp(temp->data->filename,head->data->filename)<=0)
    {
        temp->next=head;
        head=temp;
        hashtable[index]=head;//[index_2]=head;

    }
    else
    {
        while (head!=NULL)
        {
            // before comparing they must me in lowercase
            if(strcmp(temp->data->filename,head->data->filename)>0)
            {
                temp_prev=head;
                head=head->next;
                //	flag=1;
            }
            else //<=0
            {

                break;
            }
        }
        temp_prev->next=temp;
        temp->next=head;

    }

    temp=hashtable[index];//[index_2];
   // fprintf(errfptr,"HashTable.c : method name:insert_InSortedOrder status:exit1\n");
    //printf("\n from hash table:");
  /*while(temp!=NULL)
    {
        printf("  in sorted: %s  end ",temp->data->filename);
        temp=temp->next;
    }*/
    //return
   // printf("\n\n");
    //return head;*/

}/*
int compare(char a[], char b[])
{
    int c = 0;
//printf("i am in compare1");
    while( a[c] == b[c]) )//ae Amar
    {
        //printf("iam in compare2 %c   %c",a[c],b[c]);
        if( a[c] == '\0' || b[c] == '\0' )
            break;
        c++;
    }
    if( a[c] == '\0' && b[c] == '\0' )
    {
        //printf("iam in compare3 %c   %c",a[c],b[c]);
        return 0;
    }
    else
    {
        //printf("iam in compare4 %c   %c",a[c],b[c]);
        return (a[c]-b[c]);
    }
    /*
     while( tolower(a[c]) == tolower(b[c]) )//ae Amar
    {
        //printf("iam in compare2 %c   %c",a[c],b[c]);
        if( a[c] == '\0' || b[c] == '\0' )
            break;
        c++;
    }
    if( a[c] == '\0' && b[c] == '\0' )
    {
        //printf("iam in compare3 %c   %c",a[c],b[c]);
        return 0;
    }
    else
    {
        //printf("iam in compare4 %c   %c",a[c],b[c]);
        return (a[c]-b[c]);
    }


}*/

void copy_Node(struct LinkedList * node,struct LinkedList *temp)
{
    //printf("i am in copy node 1");
   // fprintf(errfptr,"HashTable.c : method name:copy_Node status:entered\n");
    node->data= (struct FileDescriptor *) malloc(sizeof(struct FileDescriptor));
    //printf("i am in copy node 2");
    strcpy(node->data->filename,temp->data->filename);
    //printf("i am in copy node 3");
    strcpy(node->data->filetype,temp->data->filetype);
    //printf("i am in copy node 4");
    node->data->filesize=temp->data->filesize;
    //printf("i am in copy node 5");
    node->data->locationblocknumber=temp->data->locationblocknumber;
    //printf("i am in copy node 6");
    strcpy(node->data->locationfullpath,temp->data->locationfullpath);
   // fprintf(errfptr,"HashTable.c : method name:copy_Node status:exit1\n");
    //printf("i am in copy node 7");

}
//struct LinkedList * search_In_HashTable(char name[100]){
struct LinkedList * search_In_HashTable(char name[filename_size])
{
    char ch_first,ch_second;
    int index,index_2,flag=0;
    struct LinkedList *node=NULL,*head=NULL,*temp=NULL;
    count_of_searchfile=0;
    ch_first=name[0];
   // fprintf(errfptr,"HashTable.c : method name:search_In_HashTable status:entered\n");
   // ch_second=name[1];
    //convert the first character to lower
    //ch_first=tolower(ch_first);
    //ch_second=tolower(ch_second);

    index=ch_first%127;
    //index_2=ch_second%26;
    //printf("i am in search 1");

    if(hashtable[index]==NULL)//[index_2]==NULL)
    {
        //return NULL;// indiacting element not found;
     //  printf(" <ia m in searchelement not found>");
    //    fprintf(errfptr,"HashTable.c : method name:search_In_HashTable status:exit1\n");
        return head;

    }
    else
    {
        temp=hashtable[index];//[index_2];
        //printf("i am in search 2");
        // traverse and create the list with head pointer to return
        while(temp!=NULL)
        {
           // printf("i am in search 3");
           // if(compare(name,temp->data->filename)==0)
           //printf("\n%s %s %d",temp->data->filetype,temp->data->filename,strlen(temp->data->filetype));
            if(strncmp(name,temp->data->filename,strlen(name))==0 )//&& strcmp(temp->data->filetype,"file")==0)
            {
               // printf("i am in search 4");
                if(flag==0)
                {
                    //printf("i am in search 5");
                    flag=1;
                    node=(struct LinkedList *) malloc(sizeof(struct LinkedList));
                    //printf("i am in search 5 final");
                    copy_Node(node,temp);
                    //printf("i am in search 6");
                    head=node;
                    node->next=NULL;
                    temp=temp->next;
                    count_of_searchfile++;
                }
                else
                {
                    //printf("i am in search 6");
                    node=(struct LinkedList *) malloc(sizeof(struct LinkedList));
                    copy_Node(node,temp);
                    node->next=head;
                    head=node;
                    temp=temp->next;
                    count_of_searchfile++;
                }
            }
            else if(strcmp(name,temp->data->filename) >=0)//compare(name,temp->data->filename)>0)
            {
                //printf("i am in search 7");
                temp=temp->next;
            }
            else
            {
                //printf("i am in search 8");
                	//temp=temp->next;// remember to remove this comment only if search is 								case insensitive

                break;
            }
        }
        //printf("\n ia m out in search");
        //return head;
    }
    //fprintf(errfptr,"HashTable.c : method name:search_In_HashTable status:exit2\n");
    return head;
    /*	if(head!=NULL){


    	while(head!=NULL){
    	printf("%s",head->data->filename);head=head->next;
    	}
    	}
    	else{

        printf("\nHashTable.c(from search method):\t ")
    	}
    */
}
void   insert_Into_HashTable(struct FileDescriptor *fd)
{
    //insert_IntoHashTable(struct FileDescriptor fd){
// take the first character and hash it to the appropriate location
    char name[filename_size],ch_first,ch_second;

    int index,index_2;
    struct LinkedList *node=NULL;//(struct LinkedList *) malloc(sizeof(struct LinkedList));
    struct LinkedList *temp=NULL;
//fprintf(errfptr,"HashTable.c : method name:insert_Into_HashTable status:entered\n");
    node= (struct LinkedList *) malloc(sizeof(struct LinkedList));
    node->data=fd;
    node->next=NULL;

   // printf("\niam in insert %s end ",fd->filename);

    ch_first=fd->filename[0];
    //ch_second=fd->filename[1];
    //convert the first character to lower
    //ch_first=tolower(ch_first);
    //ch_second=tolower(ch_second);

    index=ch_first%127;
    //index_2=ch_second%26;

    if(hashtable[index]==NULL)//[index_2]==NULL)
    {
        hashtable[index] = node;//[index_2] = node;
        //printf("in hashtable :%s\n",node->data->filename);
    }
    else
    {

        insert_InSortedOrder(node,index);
    }

  //  fprintf(errfptr,"HashTable.c : method name:insert_Into_HashTable status:exit1\n");
}

// delete_from_hash is called only when you are sure that it is goinf to be deleted.. that means if directory is empy or file is asked to be deleted .. what i mean to say is all the checkings have to be done prior calling this delete function.This delete function simple deletes nd does not check whether its directory or file or directory contains files or not.

// extra modification if you are asked to delete a file call this function to know whether such file in given directory exist or no
// i am deleting only node not file descriptors
//this method is setting the location block number of file descriptor to 0int  delete_From_HashTable(char locationfullpath[300]) // all i need is name of file/dir and complete path
int  delete_From_HashTable(char locationfullpath[locationpath_size]) // all i need is name of file/dir and complete path
{

    char delim[]="/",save_locationpath[locationpath_size];
    char *result=NULL,*prev_result=NULL;
    char ch_first,ch_second;
    char filename[filename_size];
    int index,index_2,flag=0;
    struct LinkedList *temp=NULL,*temp_prev=NULL,*save_temp=NULL,*head=NULL;//*node=NULL,*head=NULL,
    //fprintf(errfptr,"HashTable.c : method name:delete_From_HashTable status:entered\n");
    strcpy(save_locationpath,locationfullpath);
    result=strtok(save_locationpath,delim);

    while (result!=NULL)
    {
       // printf("%s\t",result);
        prev_result=result;
        result=strtok(NULL,delim);
    }

    strcpy(filename,prev_result);
    //printf("%s\t",filename);
    //printf("%s\t",locationfullpath);

    //strcpy(filename,fd->filename);
    //strcpy(locationfullpath,fd->locationfullpath);
    //Take the first character
    ch_first=filename[0];
    //ch_second=filename[1];
    //convert the first character to lower
    //ch_first=tolower(ch_first);
    //ch_second=tolower(ch_second);

    index=ch_first%127;
    //index_2=ch_second%26;
    //assumption 1-- element exist
    temp=hashtable[index];//[index_2];
    // make head and temp_prev to point to temp which is pointing to first location of the list
    temp_prev=temp;
    head=temp;
    // if element does not exist
    if(temp==NULL) {
     //fprintf(errfptr,"HashTable.c : method name:delete_From_HashTable status:exit1\n");
        return 0;
    }
    //if element deleted is at the head
    if(strcmp(filename,temp->data->filename)==0 && strcmp(locationfullpath,temp->data->locationfullpath)==0)
    {
        head=head->next;
        hashtable[index]=head;//[index_2]=head;
        save_temp=temp;
        temp_prev->next=temp->next;
        //free(save_temp->data); i am delting file descriptor also which is
        free(save_temp);
      //fprintf(errfptr,"HashTable.c : method name:delete_From_HashTable status:exit2\n");
        return 1;


    }
    //printf(" 1 ");
    // traverse and create the list with head pointer to return
    else
    {
        while(temp!=NULL)
        {

            //	printf("i am in search 3");
            if(strcmp(filename,temp->data->filename)==0)
            {

                if(strcmp(locationfullpath,temp->data->locationfullpath)==0)
                {
                    // delete and break

                    save_temp=temp;

                    temp_prev->next=temp->next;

                    free(save_temp);
       //             fprintf(errfptr,"HashTable.c : method name:delete_From_HashTable status:exit3\n");

                    return 1;
                }
                else
                {
                    //name is same but path is not same

                    temp_prev=temp;

                    temp=temp->next;
                }
            }
            else
            {
                //assuming element exist

                temp_prev=temp;

                temp=temp->next;
            }
        }
        if(temp==NULL){
        //fprintf(errfptr,"HashTable.c : method name:delete_From_HashTable status:exit4\n");
         return 0;
         }

    }
    //temp=hashtable[index][index_2];
    /*while(temp!=NULL){
    printf("%s    %s\n",temp->data->filename,temp->data->locationfullpath);
    temp=temp->next;
    }	*/
    //fprintf(errfptr,"HashTable.c : method name:delete_From_HashTable status:exit5\n");
}
